﻿using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Xml.Linq;
using DeepCast.Location;
using FBEntities.FBConnections;
using FBEntities.FBConnections.User;
using FBEntities.FBObjects;
using FBEntities.FBObjects.User;
using FacebookXmpp;
using Microsoft.WindowsMobile.Samples.Location;
using Newtonsoft.Json.Linq;
using XDAFacebook;
using XFControls;
using XFControls.Utils;
using XFControls.XFPanels.XFPanelItems;
using System;
using FBEntities;

#pragma warning disable 1591
namespace XFItemControls.XFPanels.XFPanelItems
{
    public class XFWorkerGeneric : IXFItemLoadingWorker
    {
        private const WorkerSyncState _syncState = WorkerSyncState.None;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public event EventHandler Work;
        public event EventHandler WorkerDone;

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (Work != null)
                Work(this, new EventArgs());
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            Work = null;
        }
    }

    public class XFWorkerGPS : IXFItemLoadingWorker
    {
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private readonly XFItemSimpleText _text;
        private WebDownloaderWrapper _wrapper;
        private Gps _gps;
        private System.Threading.Timer _timer;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public event EventHandler WorkerDone;
        public FBPlaces Places;

        public XFWorkerGPS(XFItemSimpleText text)
        {
            _text = text;
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (Settings.position == 0 || Settings.position == 1)
            {
                _gps = new Gps();

                _gps.LocationChanged += (s, args) =>
                {
                    var pos = args.Position;
                    if (pos == null || !pos.LatitudeValid || !pos.LongitudeValid) return;

                    string lat = pos.Latitude.ToString();
                    string lon = pos.Longitude.ToString();

                    lat = lat.Replace(',', '.');
                    lon = lon.Replace(',', '.');

                    GetPlace(lat, lon);
                };

                _gps.Open();

                if (Settings.position == 1)
                {
                    _timer = new System.Threading.Timer(TimerTick, null, 0, 100);
                }
            }
            else
            {
                _timer = new System.Threading.Timer(TimerTick, null, 0, 100);
            }
        }

        void TimerTick(object sender)
        {
            _timer.Dispose();
            var loc = CellTowerLocationProvider.CurrentLocationCell();
            if (double.IsNaN(loc.Latitude) || double.IsNaN(loc.Longitude)) return;

            if (Settings.position == 1)
            {
                _gps.Close();
            }

            string lat = loc.Latitude.ToString();
            string lon = loc.Longitude.ToString();

            lat = lat.Replace(',', '.');
            lon = lon.Replace(',', '.');

            GetPlace(lat, lon);
        }

        private void GetPlace(string lat, string lon)
        {
            _text.SetString(string.Format(Settings.LocalizationStrings.GotGPS, lat, lon));
            _text.Invalidate(true);
            Application.DoEvents();



            Places = new FBPlaces(lat, lon);
            _wrapper = Places.GetDownloadWrapper();

            _wrapper.GetResults += (o, e) =>
                                   {
                                       Places.Parse(e.Text);
                                       if (WorkerDone != null)
                                           WorkerDone(this, new EventArgs());
                                   };
            _wrapper.BeginDownload();
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;

            if (_gps != null && _gps.Opened)
                _gps.Close();
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadUserData : IXFItemLoadingWorker
    {
        public readonly FBPerson Person;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadUserData(FBPerson pers)
        {
            Person = pers;
        }
        public event EventHandler WorkerDone;

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            string url = "https://graph." + Settings.Domain + ".com/" + Person.id + "?fields=birthday,location,relationship_status,gender,email,link,activities,interests,music,television,movies,books,quotes,bio&" + FBParseUtilities.authKey;
            _wrapper = new WebDownloaderWrapper(url);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            Person.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadGroup : IXFItemLoadingWorker
    {
        public readonly FBGroup Group;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadGroup(FBGroup group)
        {
            Group = group;
        }
        public event EventHandler WorkerDone;

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            string url = "https://graph." + Settings.Domain + ".com/" + Group.id + "?" + FBParseUtilities.authKey;
            _wrapper = new WebDownloaderWrapper(url);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            Group.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadCheckins : IXFItemLoadingWorker
    {
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public event EventHandler WorkerDone;

        public void DoWork()
        {
            var me = XFItemControlUtils.Me.Me;

            if (me.Checkins.Parsed)
                me.Checkins.data.Clear();
            _wrapper = me.Checkins.Parse(me.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            var me = XFItemControlUtils.Me.Me;
            me.Checkins.Parse(JObject.Parse(e.Text));

            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadFriends : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadFriends(FBPerson pers)
        {
            _pers = pers;
        }
        public event EventHandler WorkerDone;

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_pers.Friends.Parsed)
                _pers.Friends.data.Clear();
            _wrapper = _pers.Friends.Parse(_pers.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            FBCache.Cache(e.Text, "friends");
            FBCache.SaveCache();
            _pers.Friends.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadMembers : IXFItemLoadingWorker
    {
        private readonly FBGroup _group;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public FBGroup ParsedGroup
        {
            get { return _group; }
        }

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadMembers(FBGroup group)
        {
            _group = group;
        }
        public event EventHandler WorkerDone;

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_group.Members.Parsed)
                _group.Members.data.Clear();
            _wrapper = _group.Members.Parse(_group.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            _group.Members.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadFriendsStatus : IXFItemLoadingWorker
    {
        public readonly FBPerson Person;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadFriendsStatus(FBPerson pers)
        {
            Person = pers;
        }
        public event EventHandler WorkerDone;

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            _wrapper = XFItemControlUtils.GetFQL("Select uid, message from status where uid in (select uid2 from friend where uid1 = me())");
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            var o = JArray.Parse(e.Text);
            if (o != null)
            {
                //var array = (JArray)o;
                var friends = Person.Friends.data;

                foreach (JToken token in o)
                {
                    var to = ((JObject)token);
                    var friend = friends.Find(f => f.id == to["uid"].ToString());

                    if (friend == null) continue;
                    friend.status = to["message"].ToString();
                }
            }
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadWall : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;
        private string _url;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadWall(FBPerson pers)
        {
            _pers = pers;
        }

        public XFWorkerLoadWall(string url)
        {
            _url = url;
        }

        public event EventHandler WorkerDone;

        public FBPerson ParsedPerson
        {
            get { return _pers; }
        }

        public FBFeed Feed;

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (!string.IsNullOrEmpty(_url))
            {
                Feed = new FBFeed();

                _wrapper = new WebDownloaderWrapper(_url);
                _wrapper.GetResults += (o, e) =>
                {
                    Feed.Parse(JObject.Parse(e.Text));
                    if (WorkerDone != null)
                        WorkerDone(this, new EventArgs());
                };

                _wrapper.BeginDownload();
            }

            if (_pers == null) return;

            if (_pers.Feed.Parsed)
                _pers.Feed.data.Clear();
            _wrapper = _pers.Feed.Parse(_pers.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            _pers.Feed.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadGroupWall : IXFItemLoadingWorker
    {
        private readonly FBGroup _group;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadGroupWall(FBGroup group)
        {
            _group = group;
        }

        public event EventHandler WorkerDone;

        public FBGroup ParsedGroup
        {
            get { return _group; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_group == null) return;

            if (_group.Feed.Parsed)
                _group.Feed.data.Clear();
            _wrapper = _group.Feed.Parse(_group.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            _group.Feed.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadAlbum : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadAlbum(FBPerson pers)
        {
            _pers = pers;
        }
        public event EventHandler WorkerDone;

        public FBPerson ParsedPerson
        {
            get { return _pers; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_pers.Albums.Parsed)
                _pers.Albums.data.Clear();
            _wrapper = _pers.Albums.Parse(_pers.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            _pers.Albums.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadComments : IXFItemLoadingWorker
    {
        private FBPost _post;
        private readonly string _url;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }

        public XFWorkerLoadComments(FBPost post)
        {
            _post = post;
        }

        public XFWorkerLoadComments(string url)
        {
            _url = url;
        }

        public event EventHandler WorkerDone;

        public FBPost ParsedPost
        {
            get { return _post; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (!string.IsNullOrEmpty(_url))
            {
                _post = new FBPost();
                _wrapper = new WebDownloaderWrapper(_url);
                _wrapper.GetResults += (o, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Text))
                    {
                        var jobj = JObject.Parse(e.Text);
                        _post.Comments.Parse(jobj);
                    }

                    if (WorkerDone != null)
                        WorkerDone(this, new EventArgs());
                };

                _wrapper.BeginDownload();
                return;
            }

            if (_post == null) return;

            if (_post.Comments.Parsed)
                _post.Comments.data.Clear();

            int offset = _post.comments != null ? _post.comments.count - 25 : 0;
            string limit = _post.comments != null && _post.comments.count > 25 ? "?limit=25&offset=" + offset : "";

            if (offset > 0 && offset < 25)
            {
                _post.Comments.paging = new FBPaging
                {
                    previous = "https://graph." +
                    Settings.Domain + ".com/" +
                    _post.id + "/comments?limit=" +
                    offset + "&offset=0"
                };
            }

            string batchString = "[{\"method\": \"GET\", \"relative_url\": \"" + _post.id + "/likes\"},{\"method\": \"GET\", \"relative_url\": \"" + _post.id + "/comments" + limit + "\"}]";
            var args = new Dictionary<string, string> { { "access_token", FBParseUtilities.authKeySplit }, { "batch", batchString } };
            _wrapper = new WebDownloaderWrapper("https://graph." + Settings.Domain + ".com/") { PostData = args };

            _wrapper.GetResults += WrapperGetBatchResults;
            _wrapper.BeginPost();
        }

        private void WrapperGetBatchResults(object sender, TextEventArgs e)
        {
            var batch = new FBBatch(e.Text);

            var obj = JObject.Parse(batch.Results[0]);

            _post.PeopleWhoLiked.Parse(obj);
            _post.PeopleWhoLiked.count = ((JArray)obj["data"]).Count;

            string text = batch.Results[1];

            var rx = new Regex(@"\\[uU](?<numb>[0-9A-Fa-f]{4})");
            text = rx.Replace(text, match => ((char)Int32.Parse(match.Groups["numb"].Value, NumberStyles.HexNumber)).ToString());

            obj = JObject.Parse(text);
            string prev = _post.Comments.paging == null ? "" : _post.Comments.paging.previous;

            _post.Comments.Parse(obj);

            if (!string.IsNullOrEmpty(prev))
            {
                if (_post.Comments.paging == null)
                    _post.Comments.paging = new FBPaging();

                _post.Comments.paging.previous = prev;
            }

            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadLikes : IXFItemLoadingWorker
    {
        private FBPost _post;
        private string _url;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }

        public XFWorkerLoadLikes(FBPost post)
        {
            _post = post;
        }

        public XFWorkerLoadLikes(string url)
        {
            _url = url;
        }

        public event EventHandler WorkerDone;

        public FBPost ParsedPost
        {
            get { return _post; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (!string.IsNullOrEmpty(_url))
            {
                _post = new FBPost();
                _wrapper = new WebDownloaderWrapper(_url);
                _wrapper.GetResults += (o, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Text))
                    {
                        var jobj = JObject.Parse(e.Text);
                        _post.PeopleWhoLiked.Parse(jobj);
                    }

                    if (WorkerDone != null)
                        WorkerDone(this, new EventArgs());
                };

                _wrapper.BeginDownload();
                return;
            }

            if (_post == null) return;

            if (_post.PeopleWhoLiked.Parsed)
                _post.PeopleWhoLiked.data.Clear();

            int offset = _post.likes != null ? _post.likes.count - 25 : 0;
            string limit = _post.likes != null && _post.likes.count > 25 ? "&limit=25&offset=" + offset : "";

            if (offset > 0 && offset < 25)
            {
                _post.PeopleWhoLiked.paging = new FBPaging
                {
                    previous = "https://graph." +
                    Settings.Domain + ".com/" +
                    _post.id + "/likes?" + FBParseUtilities.authKey + "&limit=" +
                    offset + "&offset=0"
                };
            }

            _wrapper = new WebDownloaderWrapper("https://graph." + Settings.Domain + ".com/" + _post.id + "/likes?" + FBParseUtilities.authKey + limit);

            _wrapper.GetResults += WrapperResults;
            _wrapper.BeginDownload();
        }

        private void WrapperResults(object sender, TextEventArgs e)
        {
            var obj = JObject.Parse(e.Text);

            string prev = _post.PeopleWhoLiked.paging == null ? "" : _post.PeopleWhoLiked.paging.previous;

            _post.PeopleWhoLiked.Parse(obj);
            _post.PeopleWhoLiked.count = ((JArray)obj["data"]).Count;

            _post.Comments.Parse(obj);

            if (!string.IsNullOrEmpty(prev))
            {
                if (_post.PeopleWhoLiked.paging == null)
                    _post.PeopleWhoLiked.paging = new FBPaging();

                _post.PeopleWhoLiked.paging.previous = prev;
            }

            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadNewsFeeds : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private readonly string _url;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public event EventHandler WorkerDone;

        public XFWorkerLoadNewsFeeds(FBPerson pers)
        {
            _pers = pers;
        }

        public XFWorkerLoadNewsFeeds(string url)
        {
            _url = url;
        }

        public FBPerson ParsedPerson
        {
            get { return _pers; }
        }

        public FBHome Home { get; private set; }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_wrapper != null)
                _wrapper.Dispose();

            _wrapper = null;
            if (!string.IsNullOrEmpty(_url))
            {
                Home = new FBHome();

                _wrapper = new WebDownloaderWrapper(_url);
                _wrapper.GetResults += (o, e) =>
                {
                    Home.Parse(JObject.Parse(e.Text));
                    if (WorkerDone != null)
                        WorkerDone(this, new EventArgs());
                };

                _wrapper.BeginDownload();
            }
            if (_pers == null) return;

            if (_pers.Home.Parsed)
                _pers.Home.data.Clear();

            if (string.IsNullOrEmpty(_pers.id))
                _wrapper = _pers.Home.Parse("me");
            else
                _wrapper = _pers.Home.Parse(_pers.id);

            _wrapper.GetResults += (o, e) =>
            {
                _pers.Home.Parse(JObject.Parse(e.Text));
                if (WorkerDone != null)
                    WorkerDone(this, new EventArgs());
            };

            _wrapper.BeginDownload();
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadInbox : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadInbox(FBPerson pers)
        {
            _pers = pers;
        }
        public event EventHandler WorkerDone;

        public FBPerson ParsedPerson
        {
            get { return _pers; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_pers.Inbox.Parsed)
                _pers.Inbox.data.Clear();
            _wrapper = _pers.Inbox.Parse(_pers.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            _pers.Inbox.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadGroups : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadGroups(FBPerson pers)
        {
            _pers = pers;
        }
        public event EventHandler WorkerDone;

        public FBPerson ParsedPerson
        {
            get { return _pers; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_pers.Groups.Parsed)
                _pers.Groups.data.Clear();
            _wrapper = _pers.Groups.Parse(_pers.id);
            _wrapper.GetResults += WrapperGetResults;
            _wrapper.BeginDownload();
        }

        void WrapperGetResults(object sender, TextEventArgs e)
        {
            _pers.Groups.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadNotes : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadNotes(FBPerson pers)
        {
            _pers = pers;
        }
        public event EventHandler WorkerDone;

        public FBPerson ParsedPerson
        {
            get { return _pers; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_pers.Notes.Parsed)
                _pers.Notes.data.Clear();
            _wrapper = _pers.Notes.Parse(_pers.id);
            _wrapper.GetResults += WraperGetResults;
            _wrapper.BeginDownload();
        }

        void WraperGetResults(object sender, TextEventArgs e)
        {
            _pers.Notes.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadEvents : IXFItemLoadingWorker
    {
        private readonly FBPerson _pers;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadEvents(FBPerson pers)
        {
            _pers = pers;
        }
        public event EventHandler WorkerDone;

        public FBPerson ParsedPerson
        {
            get { return _pers; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_pers.Events.Parsed)
                _pers.Events.data.Clear();
            _wrapper = _pers.Events.Parse(_pers.id);
            _wrapper.GetResults += WraperGetResults;
            _wrapper.BeginDownload();
        }

        void WraperGetResults(object sender, TextEventArgs e)
        {
            _pers.Events.Parse(JObject.Parse(e.Text));
            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadAlbums : IXFItemLoadingWorker
    {
        private readonly FBAlbum _album;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public event EventHandler WorkerDone;
        private readonly string _url;

        public XFWorkerLoadAlbums(FBAlbum album)
        {
            _album = album;
        }

        public XFWorkerLoadAlbums(FBAlbum album, string url)
        {
            _album = album;
            _url = url;
        }

        public FBAlbum Album
        {
            get { return _album; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_wrapper != null)
                _wrapper.Dispose();

            _wrapper = null;

            if (!string.IsNullOrEmpty(_url))
            {
                _wrapper = new WebDownloaderWrapper(_url);
                _wrapper.GetResults += (o, e) =>
                {
                    _album.Photos.Parse(JObject.Parse(e.Text));
                    if (WorkerDone != null)
                        WorkerDone(this, new EventArgs());
                };

                _wrapper.BeginDownload();
            }
            else if (_album != null)
            {
                _wrapper = _album.Photos.Parse(_album.id);

                _wrapper.GetResults += (o, e) =>
                {
                    _album.Photos.Parse(JObject.Parse(e.Text));
                    if (WorkerDone != null)
                        WorkerDone(this, new EventArgs());
                };
                _wrapper.BeginDownload();
            }
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_wrapper != null)
                _wrapper.Dispose();
        }
    }

    public class XFWorkerLoadNotifications : IXFItemLoadingWorker
    {
        private readonly FBNotifications _notes;
        private const WorkerSyncState _syncState = WorkerSyncState.None;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public XFWorkerLoadNotifications(FBNotifications notes)
        {
            _notes = notes;
        }
        public event EventHandler WorkerDone;

        public FBNotifications Notifications
        {
            get { return _notes; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            _notes.ManualUpdate();

            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
        }
    }

    public class XFWorkerPostLike : IXFItemLoadingWorker
    {
        private readonly FBPost _post;
        private readonly bool _remove;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _wrapper;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public event EventHandler WorkerDone;

        public XFWorkerPostLike(FBPost post, bool remove)
        {
            _remove = remove;
            _post = post;
        }

        public bool Success { get; set; }

        public FBPost ParsedPost
        {
            get { return _post; }
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (_wrapper != null)
                _wrapper.Dispose();

            _wrapper = _post.Like();
            _wrapper.GetResults += (o, e) =>
                                               {
                                                   _post.PeopleWhoLiked.count += _remove ? -1 : 1;
                                                   Success = !FBParseUtilities.HasError(e.Text);

                                                   if (WorkerDone != null)
                                                       WorkerDone(this, new EventArgs());
                                               };

            if (_remove)
                _wrapper.BeginDelete();
            else
                _wrapper.BeginPost();
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
        }
    }

    public class XFWorkerGetSearch : IXFItemLoadingWorker
    {
        private readonly string _search;
        private readonly string _type;
        private const WorkerSyncState _syncState = WorkerSyncState.ForceSync;
        private WebDownloaderWrapper _downloader;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public FBSearch Search;
        public event EventHandler WorkerDone;

        public XFWorkerGetSearch(string search, string type)
        {
            _search = search;
            _type = type;
        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            string url = "https://graph." + Settings.Domain + ".com/search?q=" + _search + "&type=" + _type + "&" + FBParseUtilities.authKey;

            _downloader = new WebDownloaderWrapper(url);

            _downloader.GetResults += (sender, e) =>
            {
                JObject o = JObject.Parse(e.Text);

                Search = new FBSearch();
                Search.Parse(o);

                if (WorkerDone != null)
                    WorkerDone(this, new EventArgs());
            };
            _downloader.BeginDownload();
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_downloader != null)
                _downloader.Dispose();
        }
    }

    public class XFWorkerChatLogin : IXFItemUpdatingWorker
    {
        private const WorkerSyncState _syncState = WorkerSyncState.ForceAsync;

        public WorkerSyncState AsyncState { get { return _syncState; } set { } }
        public event EventHandler WorkerDone;
        public Action<string> WorkerUpdate { get; set; }

        private WebDownloaderWrapper _downloader;

        public XFWorkerChatLogin()
        {
            if (XFChat.Dashboard == null)
                XFChat.Dashboard = new Dashboard(Settings.appId, Settings.auth_key);

        }

        #region IXFItemLoadingWorker Members

        public void DoWork()
        {
            if (XFChat.Dashboard.IsAuthenticated)
            {
                if (WorkerDone != null)
                    WorkerDone(this, new EventArgs());
                return;
            }

            XFChat.Dashboard.WorkerState = WorkerUpdate;
            XFChat.Dashboard.EnsureAuthenticated();

            if (XFChat.Dashboard.IsAuthenticated)
            {
                WorkerUpdate("Fetching friends");
                XFChat.Dashboard.UpdateFriends();
            }

            if (WorkerDone != null)
                WorkerDone(this, new EventArgs());
        }

        #endregion

        public void Dispose()
        {
            WorkerDone = null;
            if (_downloader != null)
                _downloader.Dispose();
        }
    }
}
#pragma warning restore 1591
